package com.kezesong.leasing.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kezesong.leasing.common.enums.ReturnCodeEnum;
import com.kezesong.leasing.common.exception.CommonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Component
public class WeixinService {

    Logger logger = LoggerFactory.getLogger(getClass());


    @Value("${appId}")
    private String appId;

    @Value("${appSecret}")
    private String appSecret;


    //https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
    @Value("${jscode2sessionUrl}")
    private String jscode2sessionUrl;


    @Value("${mchid}")
    private String mchid;

    @Value("${jsapiUrl}")
    private String jsapiUrl;

    @Value("${notifyUrl}")
    private String notifyUrl;










    /**
     *
     * <p>
     *     前端js调用示例：
     *     wx.login({
     *   success(res) {
     *     if (res.code) {
     *       // 获取到用户的 code
     *       console.log('code:', res.code);
     *     } else {
     *       console.log('获取用户登录态失败', res.errMsg);
     *     }
     *   }
     * });
     * </p>
     *
     *
     * 说明文档：
     * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
     *
     * 請求示例：
     * GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
     *
     * 返回結果
     * {
     * "openid":"xxxxxx",
     * "session_key":"xxxxx",
     * "unionid":"xxxxx",
     * "errcode":0,
     * "errmsg":"xxxxx"
     * }
     * @param code
     * @return
     */
    public JSONObject getWechatUserInfo(String code){
        String url = String.format(jscode2sessionUrl,appId,appSecret,code);
        String result = HttpUtil.get(url);
        JSONObject jsonObject = JSON.parseObject(result);
        logger.info("UserInfoServiceImpl.getUserInfoByCode:{}", jsonObject);
        return jsonObject;
    }


    /**
     *<p>
     *     前端示js调用示例：
     *     wx.requestPhoneNumber({
     *   success(res) {
     *     const encryptedData = res.encryptedData; // 加密的手机号数据
     *     const iv = res.iv;                       // 加密算法的初始向量
     *     // 将 encryptedData 和 iv 发送到服务器
     *     sendToServer(res.code, encryptedData, iv);
     *   },
     *   fail() {
     *     console.log('用户拒绝提供手机号');
     *   }
     * });
     *
     *</p>
     *
     *
     * @param encryptedData 前端获取的
     * @param iv  前端获取的
     * @param sessionKey
     * @return
     * @throws Exception
     */
    public String decryptPhoneNumber(String encryptedData, String iv, String sessionKey) throws CommonException {
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
            byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);
            byte[] ivBytes = Base64.getDecoder().decode(iv);

            SecretKeySpec keySpec = new SecretKeySpec(sessionKeyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec, new SecureRandom());

            byte[] original = cipher.doFinal(encryptedBytes);
            return new String(original, "UTF-8");
        } catch (Exception e) {
            logger.error("WeixinService.decryptPhoneNumber failed", e);
            throw new CommonException(ReturnCodeEnum.DESCRIPT_WEIXIN_PHONE_ERROR);
        }
    }


    /**
     *
     * 生成预支付订单
     *
     * 流程说明图 ：
     * https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_2.shtml
     *
     * 生成预支付订单：
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
     *
     * 调用示例：
     *
             {
             "mchid": "1900006XXX",
             "out_trade_no": "1217752501201407033233368318",
             "appid": "wxdace645e0bc2cXXX",
             "description": "Image形象店-深圳腾大-QQ公仔",
             "notify_url": "https://www.weixin.qq.com/wxpay/pay.php",
             "amount": {
             "total": 1,
             "currency": "CNY"
             },
             "payer": {
             "openid": "o4GgauInH_RCEdvrrNGrntXDuXXX"
             }
             }


     正常响应：

         {
         "prepay_id": "wx26112221580621e9b071c00d9e093b0000"
         }
     *
     */
    public String createPrepayNumber(String openId, String outTradeNo, BigDecimal totalPrice,String payDescription){
        Map<String, Object> params = new HashMap<>();
        params.put("mchid",mchid);
        params.put("appid",appId);
        params.put("out_trade_no",outTradeNo);
        params.put("description",payDescription);
        params.put("notify_url",notifyUrl);

        Map<String, Object> amount = new HashMap<>();
        amount.put("total", totalPrice);
        amount.put("currency", "CNY");
        params.put("amount",amount);

        Map<String, Object> payer = new HashMap<>();
        payer.put("openid",openId);
        params.put("payer",payer);

        String result = HttpUtil.post(jsapiUrl, params);
        logger.info("UserInfoServiceImpl.createPrepayNumber:{}", result);
        JSONObject jsonObject = JSON.parseObject(result);
        String payId = jsonObject.getString("prepay_id");
        return payId;
    }


    /**
     * 支付成功，微信通知本站接口
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_5.shtml
     */
    public void notifyPayResult(){

    }

    /**
     * 主动查询支付结果
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_2.shtml
     */
    public void  queryPayResult(){

    }

}
